import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Paint;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;

import javax.swing.JFrame;

import org.apache.commons.collections15.Transformer;

import edu.uci.ics.jung.algorithms.layout.CircleLayout;
import edu.uci.ics.jung.algorithms.layout.Layout;
import edu.uci.ics.jung.graph.DirectedSparseGraph;
import edu.uci.ics.jung.visualization.RenderContext;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.DefaultModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.renderers.Renderer;
import edu.uci.ics.jung.visualization.transform.shape.GraphicsDecorator;

public class GUI {
	private static ArrayList<String> arrayListOfDistances = new ArrayList<String>();
	private static ArrayList<String> arrayListOfTurnRestrictedDistances = new ArrayList<String>();

	public static void createGUI() {
		final DirectedSparseGraph<String, String> g = new DirectedSparseGraph<String, String>();

		/*********************** Adding Vertex *********/
		for (int i = 0; i < ShortestPath.n; i++) {
			g.addVertex(String.valueOf(i));
		}

		for (int i = 0; i < ShortestPath.n; i++) {
			for (int j = 0; j < ShortestPath.n; j++) {
				if (ShortestPath.linkcost[i][j] != 0
						&& ShortestPath.linkcost[i][j] != Double.POSITIVE_INFINITY) {
					g.addEdge(String.valueOf(ShortestPath.linkcost[i][j]),
							String.valueOf(i), String.valueOf(j));
					storeEdges(i, j);
				}
			}
		}
		
		/*For restricted edges*/
		for (int i = 0; i < ShortestPath.n; i++) {
			for (int j = 0; j < ShortestPath.n; j++) {
				if (ShortestPath.linkcost[i][j] != 0
						&& ShortestPath.linkcost[i][j] != Double.POSITIVE_INFINITY) {
					storeRestrictedEdges(i, j);
				}
			}
		}
		

		VisualizationViewer<String, String> vv = new VisualizationViewer<String, String>(
				new CircleLayout<String, String>(g), new Dimension(600, 600));

		Transformer<String, String> transformer = new Transformer<String, String>() {
			@Override
			public String transform(String arg0) {
				return arg0;
			}
		};
		vv.getRenderContext().setVertexLabelTransformer(transformer);
		transformer = new Transformer<String, String>() {
			@Override
			public String transform(String arg0) {
				return arg0;
			}
		};

		/**** Colour for edge *****/
		Transformer<String, Paint> edgePaint = new Transformer<String, Paint>() {
			public Paint transform(String s) {
				for (int i = 0; i < arrayListOfDistances.size(); i++) {
					if (s.equals(arrayListOfDistances.get(i).toString())) {
						return Color.GREEN;
					}
				}

				for (int i = 0; i < arrayListOfTurnRestrictedDistances.size(); i++) {
					if (s.equals(arrayListOfTurnRestrictedDistances.get(i)
							.toString())) {
						return Color.RED;
					}
				}

				return Color.WHITE;
			}
		};

		Transformer<String, Stroke> edgeStroke = new Transformer<String, Stroke>() {
			float dash[] = { 10.0f };

			public Stroke transform(String s) {
				return new BasicStroke(1.0f, BasicStroke.CAP_BUTT,
						BasicStroke.JOIN_MITER, 10.0f, dash, 0.0f);
			}
		};

		vv.getRenderContext().setEdgeDrawPaintTransformer(edgePaint);
		vv.getRenderContext().setEdgeStrokeTransformer(edgeStroke);
		/***************************/

		vv.getRenderContext().setEdgeLabelTransformer(transformer);
		vv.getRenderer().setVertexRenderer(new MyRenderer());

		// The following code adds capability for mouse picking of
		// vertices/edges. Vertices can even be moved!
		final DefaultModalGraphMouse<String, Number> graphMouse = new DefaultModalGraphMouse<String, Number>();
		vv.setGraphMouse(graphMouse);
		graphMouse.setMode(ModalGraphMouse.Mode.PICKING);

		JFrame frame = new JFrame();
		frame.getContentPane().add(vv);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.pack();
		frame.setVisible(true);
	}

	public static void storeRestrictedEdges(int i, int j) {
		ArrayList<String> arrayList = new ArrayList<String>(
				ShortestPath.setOfTurnRestrictions);
		for (int k = 0; k < arrayList.size(); k++) {
			int left = Integer
					.parseInt(arrayList.get(k).toString().split(",")[0]);
			int middle = Integer.parseInt(arrayList.get(k).toString()
					.split(",")[1]);
			int right = Integer
					.parseInt(arrayList.get(k).toString().split(",")[2]);
			if ((left == i && middle == j)) {
				if (!arrayListOfDistances.contains(ShortestPath.linkcost[i][j])) {
					arrayListOfTurnRestrictedDistances.add(String
							.valueOf(ShortestPath.linkcost[i][j]));
				}
			}
			if ((middle == i && right == j)) {
				if (!arrayListOfDistances.contains(ShortestPath.linkcost[i][j])) {
					arrayListOfTurnRestrictedDistances.add(String
							.valueOf(ShortestPath.linkcost[i][j]));
				}
			}
		}

	}

	private static int counter = 0;

	public static void storeEdges(int i, int j) {
		if (ShortestPath.arrayList.get(counter).intValue() == i
				&& ShortestPath.arrayList.get(counter + 1).intValue() == j) {
			arrayListOfDistances.add(String
					.valueOf(ShortestPath.linkcost[i][j]));
			counter++;
		}
	}

	public static ArrayList<String> getArrayListOfDistances() {
		return arrayListOfDistances;
	}

	public static void setArrayListOfDistances(
			ArrayList<String> arrayListOfDistances) {
		GUI.arrayListOfDistances = arrayListOfDistances;
	}

	static class MyRenderer implements Renderer.Vertex<String, String> {
		@Override
		public void paintVertex(RenderContext<String, String> rc,
				Layout<String, String> layout, String vertex) {
			GraphicsDecorator graphicsContext = rc.getGraphicsContext();
			Point2D center = layout.transform(vertex);
			Shape shape = null;
			Color color = null;

			shape = new Ellipse2D.Double(center.getX() - 10,
					center.getY() - 10, 10, 10);
			color = new Color(0, 127, 127);
			graphicsContext.setPaint(color);
			graphicsContext.fill(shape);
		}
	}
}